package com.helloUIBinder.server;

import com.helloUIBinder.model.BlogPost;
import com.helloUIBinder.model.Comment;
import com.helloUIBinder.model.SiteUser;
import com.helloUIBinder.service.BlogPostManager;
import com.helloUIBinder.service.SiteUserManager;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.ws.rs.*;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;


@Component
@Path("/blogPostWebService")
public class BlogPostWebService {

    private final static String SUCCESS = "SUCCESS";
    private final static String ERROR = "ERROR";
    private final static String BAD_JSON = "BAD_JSON";


    private static final Logger log = Logger.getLogger(BlogPostWebService.class);


    @Autowired
    BlogPostManager blogPostManager;

    @Autowired
    SiteUserManager siteUserManager;

    @GET
    @Path("/{param}")
    @Produces("application/json")
    @Transactional
    public BlogPost getBlogPostById(@PathParam("param") String id) {
        return blogPostManager.findBlogPostById(Integer.parseInt(id));

    }

    @GET
    @Path("/all")
    @Produces("application/json")
    @Transactional
    public List<BlogPost> getAllBlogPosts() {
        return blogPostManager.getAllBlogPosts();
    }

    @GET
    @Path("/fields")
    @Produces("application/json")
    @Transactional
    public List<String> getAllBlogPostFields() {
        Field[] fields = BlogPost.class.getDeclaredFields();
        List<String> result = new ArrayList<String>();

        for (Field f : Arrays.asList(fields)) {
            result.add(f.getName().replaceAll("\"", ""));
        }

        return result;
    }

    @GET
    @Path("/size")
    @Produces("application/json")
    @Transactional
    public Long getAllBlogPostsSize() {
        return blogPostManager.size();
    }

    @POST
    @Path("/put")
    @Produces("application/json")
    @Transactional
    public String putBlogPost(String jsonBlogPost) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        try {
            BlogPost receivedBlogPost = mapper.readValue(jsonBlogPost, BlogPost.class);
            blogPostManager.saveBlogPost(receivedBlogPost);
            return SUCCESS;
        } catch (JsonParseException ex) {
            log.error(ex.getMessage(), ex);
            return ERROR;
        } catch (JsonMappingException ex) {
            log.error(ex.getMessage(), ex);
            return ERROR;
        } catch (IOException ex) {
            log.error(ex.getMessage(), ex);
            return ERROR;
        }
    }


    @POST
    @Path("/delete")
    @Produces("application/json")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @Transactional
    public String deleteBlogPost(String jsonBlogPost) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        try {
            BlogPost receivedBlogPost = mapper.readValue(jsonBlogPost, BlogPost.class);
            blogPostManager.deleteBlogPost(receivedBlogPost);
            return SUCCESS;
        } catch (JsonParseException ex) {
            ex.printStackTrace();
            log.error(ex.getMessage(), ex);
            return BAD_JSON;
        } catch (JsonMappingException ex) {
            log.error(ex.getMessage(), ex);
            return BAD_JSON;
        } catch (IOException ex) {
            log.error(ex.getMessage(), ex);
            return BAD_JSON;
        }
    }


    @GET
    @Path("/page/{pageNumber}/{pageSize}/{sortColumn}/{direction}")
    @Produces("application/json")
    @Transactional
    public List<BlogPost> getAllBlogPostByPage(
            @PathParam("pageNumber") Integer pageNumber, @PathParam("pageSize") Integer pageSize,
            @PathParam("sortColumn") String sortColumn, @PathParam("direction") String direction) {
        if (sortColumn.equals("null") || direction.equals("null")) {
            return blogPostManager.findAllBlogPostsByPage(pageNumber, pageSize, null, null);
        } else {
            return blogPostManager.findAllBlogPostsByPage(pageNumber, pageSize, sortColumn, Sort.Direction.valueOf(direction));
        }
    }

    @PostConstruct
    @Transactional
    public void postConstruct() {
        addTestBlogs();
        addTestSiteUsers();
    }

    private void addTestBlogs() {
        Comment comment = new Comment();
        comment.setText("this is comment!");
        BlogPost blogPost = new BlogPost();
        Date currentDate = new Date();

        Calendar calendar = GregorianCalendar.getInstance();
        calendar.set(2001, Calendar.FEBRUARY, 21);

        blogPost.setDate(calendar.getTime());
        blogPost.setOwner("some Owner");

        String text = "dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddddfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd" +
                "dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd" +
                "dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd" +
                " dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd dfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddddfsd fsdfs dfsdf sdf sfsf sfs s fsdddddddd";


        blogPost.setText(text);
        blogPost.setTheme("some");
        blogPost.setCategory("my categoty");

        BlogPost blogPost1 = new BlogPost();
        blogPost1.setText("dfdfdff");
        blogPost1.setOwner("dddddd");

        Calendar calendar1 = GregorianCalendar.getInstance();
        calendar1.set(2003, Calendar.AUGUST, 22);
        blogPost1.setDate(calendar1.getTime());

        blogPostManager.saveBlogPost(blogPost);
        blogPostManager.saveBlogPost(blogPost1);

        for (int i = 0; i < 20; i++) {
            BlogPost someBlog = new BlogPost();
            someBlog.setText("ddddfffff" + String.valueOf(i));
            someBlog.setOwner("ownersdsdsd" + String.valueOf(i));
            blogPostManager.saveBlogPost(someBlog);
        }

    }

    private void addTestSiteUsers() {
        SiteUser siteUser = new SiteUser();
        siteUser.setLogin("first");
        siteUser.setPassword("first");
        siteUser.setName("first");
        siteUser.setRole(1);

        SiteUser secondUser = new SiteUser();
        secondUser.setLogin("second");
        secondUser.setPassword("second");
        secondUser.setName("second");
        secondUser.setRole(2);

        siteUserManager.saveUser(siteUser);
        siteUserManager.saveUser(secondUser);
    }

//    @Scheduled(fixedRate=5000)
//    private void testScheduler() {
//        BlogPost blogPost = new BlogPost();
//        blogPost.setTheme("Sheduler works!");
//        blogPost.setOwner("Sheduler works!");
//        blogPostManager.saveBlogPost(blogPost);
//    }


}